﻿using System;
using System.Threading;
using System.Threading.Tasks;
using Audit.Core;
using Audit.WebApi;
using K9Nano.Domain;
using K9Nano.Remoting;
using K9Nano.Runtime;
using K9Nano.Share.Exceptions;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using ISystemClock = K9Nano.Runtime.ISystemClock;

namespace K9Nano.AspNetCore.Audit
{
    public class EfCoreWebApiAuditDataProvider : WebApiAuditDataProvider
    {
        public EfCoreWebApiAuditDataProvider(IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
        {
        }


        protected IUnitOfWork Uow
        {
            get
            {
                var uow = HttpContextAccessor.HttpContext.RequestServices.GetRequiredService<IUnitOfWork>();
                uow.DisableAutoSetTenant();
                uow.DisableEvents();
                uow.DisableFilters();
                return uow;
            }
        }

        protected IRepository<AuditLog, Guid> Repository => Uow.Repository<AuditLog, Guid>();

        public override object InsertEvent(AuditEvent auditEvent)
        {
            var log = MapToLog(auditEvent);
            var id = Repository.InsertAndGetId(log);
            return id;
        }

        public override void ReplaceEvent(object eventId, AuditEvent auditEvent)
        {
            if (eventId is string id)
            {
                var log = MapToLog(auditEvent);
                log.Id = Guid.Parse(id);
                Repository.Update(log);
            }
        }

        public override T GetEvent<T>(object eventId)
        {
            if (eventId is string id)
            {
                var gid = Guid.Parse(id);
                var log = Repository.Get(gid);
                return MapToEvent<T>(log);
            }
            return default;
        }

        public override async Task<object> InsertEventAsync(AuditEvent auditEvent)
        {
            var log = MapToLog(auditEvent);
            var id = await Repository.InsertAndGetIdAsync(log, CancellationToken);
            return id;
        }

        public override async Task ReplaceEventAsync(object eventId, AuditEvent auditEvent)
        {
            if (eventId is string id)
            {
                var log = MapToLog(auditEvent);
                log.Id = Guid.Parse(id);
                await Repository.UpdateAsync(log, CancellationToken);
            }
        }

        public override async Task<T> GetEventAsync<T>(object eventId)
        {
            if (eventId is string id)
            {
                var gid = Guid.Parse(id);
                var log = await Repository.GetAsync(gid, CancellationToken);
                return MapToEvent<T>(log);
            }
            return default;
        }
    }
}